using System;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;

////////////////////////////////////////////////////////////////////////////////////////////////////
// namespace: Dimok.Data
//
// summary:	.
////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Dimok.Data{

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Attribute for configuration call. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	[ AttributeUsage(AttributeTargets.Method | AttributeTargets.Property) ]
	public class ConfigCallAttribute : Attribute {}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Summary description for RegistryBase. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public class RegistryBase{
		protected const string CONFIG_PATH = "Dimok";

		protected const string CONFIG_PATH_APPL = CONFIG_PATH + "/application";
		protected const string CONFIG_PATH_DB = CONFIG_PATH + "/db";
		protected const string CONFIG_PATH_LOGINS = CONFIG_PATH + "/logIns";
		protected const string CONFIG_PATH_CREDIT = CONFIG_PATH + "/credit";

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the configuration call method. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <returns>	The configuration call method. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static MethodBase GetConfigCallMethod(){
			StackTrace stack = new StackTrace(1);
			for( int f = 0; f < stack.FrameCount; f++ ){
				MethodBase method = stack.GetFrame(f).GetMethod();
				if( method.GetMethodImplementationFlags().ToString().IndexOf("NoInlining") >= 0 ||
						method.GetCustomAttributes(typeof(ConfigCallAttribute),true).Length > 0 )
					return method;
			}
			return null;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the caller. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <returns>	The caller. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[MethodImplAttribute(MethodImplOptions.NoInlining)]
		private static MethodBase GetCaller(){
			StackTrace stack = new StackTrace(1);
			string calleeName = stack.GetFrame(0).GetMethod().Name;
			MethodBase method = null;
			for( int f = 1; f < stack.FrameCount; f++ ){
				method = stack.GetFrame(f).GetMethod();
				if( method.Name != calleeName )break;
			}
			return method;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get value from application section in .config file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="valueName">	. </param>
		///
		/// <returns>	The appl value. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static string GetApplValue(string valueName){return GetApplValue(valueName,true);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get value from application section in .config file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="valueName">	. </param>
		/// <param name="assert">			true by default. </param>
		///
		/// <returns>	The appl value. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static string GetApplValue(string valueName,bool assert){return GetConfigValue(CONFIG_PATH_APPL,valueName,assert);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the logins value. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="valueName">	. </param>
		///
		/// <returns>	The logins value. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static string GetLoginsValue(string valueName){return GetLoginsValue(valueName,true);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the logins value. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="valueName">	. </param>
		/// <param name="assert">			true by default. </param>
		///
		/// <returns>	The logins value. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static string GetLoginsValue(string valueName,bool assert){return GetConfigValue(CONFIG_PATH_LOGINS,valueName,assert);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a database value. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="valueName">	. </param>
		///
		/// <returns>	The database value. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static string GetDBValue(string valueName){return GetDBValue(valueName,true);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a database value. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="valueName">	. </param>
		/// <param name="assert">			true by default. </param>
		///
		/// <returns>	The database value. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static string GetDBValue(string valueName,bool assert){return GetConfigValue(CONFIG_PATH_DB,valueName,assert);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get Value from key in Dimok[/*] section of .config. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <returns>	The configuration value. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static string GetConfigValue(){try{return GetConfigValue(true);}catch{throw;}}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get Value from key in Dimok[/*] section of .config. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="assert">	false by default. </param>
		///
		/// <returns>	The configuration value. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static string GetConfigValue(bool assert){return GetConfigValue(GetConfigCallMethod(),assert);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get Value from key in Dimok[/*] section of .config. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="method">	The method. </param>
		///
		/// <returns>	The configuration value. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static string GetConfigValue(MethodBase method){return GetConfigValue(method,true);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get Value from key in Dimok[/*] section of .config. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="method">	The method. </param>
		/// <param name="assert">	false by default. </param>
		///
		/// <returns>	The configuration value. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static string GetConfigValue(MethodBase method,bool assert){
			if( method == null )method = GetCaller();
			string valueName = Regex.Replace(method.Name,"^get_","");
			Regex re = new Regex("[.]?config[^.]*",RegexOptions.IgnoreCase);
			string section = re.Replace(method.DeclaringType.FullName.Replace('+','.'),"",1).Replace(".","/");
			return GetConfigValue(section,valueName,assert);//GetConfigValue(sectionPath,GetConfigCallMethod().t
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get Value from key in Dimok[/*] section of .config. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="sectionPath">	. </param>
		/// <param name="valueName">		. </param>
		///
		/// <returns>	The configuration value. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static string GetConfigValue(string sectionPath,string valueName){
			return GetConfigValue(sectionPath,valueName,false);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get Value from key in Dimok[/*] section of .config. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="sectionPath">	. </param>
		/// <param name="valueName">		. </param>
		/// <param name="assert">				false by default. </param>
		///
		/// <returns>	The configuration value. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static string GetConfigValue(string sectionPath,string valueName,bool assert){
			string s = null;
			try{
				s = GetConfigSection(sectionPath)[valueName];
			}catch( NoConfigPathException ){}
			if( s != null )return s;
			string appValueName = sectionPath.Replace("/",".").Trim('.')+"."+valueName;
			s = AppSettings(appValueName,false);
			if( s != null )return s;
			return AppSettings(Regex.Replace(appValueName,"^"+CONFIG_PATH+".","",RegexOptions.IgnoreCase),assert);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a configuration section. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="NoConfigPathException">	Thrown when noconfigpath. </exception>
		///
		/// <param name="nodePath">	Full pathname of the node file. </param>
		///
		/// <returns>	The configuration section. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static NameValueCollection GetConfigSection(string nodePath){
			object ret = ConfigurationSettings.GetConfig(nodePath);
			if( ret == null ) throw new NoConfigPathException(nodePath);
			return (NameValueCollection)ret;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the application settings. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string AppSettings(){return AppSettings(true);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the application settings. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="assert">	true by default. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string AppSettings(bool assert){
			return AppSettings(Regex.Replace(GetCaller().Name,"^get_",""),assert);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the application settings. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="valueName">	. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string AppSettings(string valueName){return AppSettings(valueName,true);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the application settings. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="NoConfigValueException">	Thrown when noconfigvalue. </exception>
		///
		/// <param name="valueName">	. </param>
		/// <param name="assert">			true by default. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string AppSettings(string valueName,bool assert){
			valueName = valueName.Replace('+', '.');
			string v = ConfigurationSettings.AppSettings[valueName];
			if( assert && v == null )throw new NoConfigValueException("appSettings",valueName);
			return v;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a single node. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="nodePath">	Full pathname of the node file. </param>
		///
		/// <returns>	The single node. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static IDictionary GetSingleNode(string nodePath){
			return (IDictionary)ConfigurationSettings.GetConfig(CONFIG_PATH+"/"+nodePath);
		}
	}
}
